package main

import (
	"fmt"
	"net/http"
)

/**
 * 在Go中, 变长参数实际上是通过切片来实现的
 **/
func myAppend(sl []int, elems ...int) []int {
	fmt.Printf("%T\n", elems) // []int
	if len(elems) == 0 {
		println("no elems to append")
		return sl
	}

	sl = append(sl, elems...)
	return sl
}

func greeting(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Welcome, Gopher!\n")
}

func times(x, y int) int {
	return x * y
}

func partialTimes(x int) func(int) int {
	return func(y int) int {
		return times(x, y)
	}
}

func main() {
	// 函数是唯一一种基于特定输入, 实现特定任务并可返回任务执行结果的代码块
	// 函数的出现也提升了整个程序界代码复用的水平

	// s := T{} // 使用复合类型字面值对结构体类型进行显式初始化
	f := func() {} // 使用便利声明形式的函数声明

	f()

	sl := []int{1, 4, 3}
	sl = myAppend(sl) // no elems to append
	fmt.Println(sl)   // [1 4˜ 3]
	sl = myAppend(sl, 4, 5, 6)
	fmt.Println(sl) // [1 4 3 4 5 6]

	fmt.Println(times(4, 5))
	fmt.Println(times(3, 5))
	fmt.Println(times(4, 5))

	timesTwo := partialTimes(4)   // 以高频乘数4为固定乘数的乘法函数
	timesThree := partialTimes(3) // 以高频乘数4为固定乘数的乘法函数
	timesFour := partialTimes(4)  // 以高频乘数4为固定乘数的乘法函数
	fmt.Println(timesTwo(5))      // 10 等价于 times(4, 5)
	fmt.Println(timesTwo(6))      // 14 等价于 times(4, 6)
	fmt.Println(timesThree(5))    // 15 等价于 times(3, 5)
	fmt.Println(timesThree(6))    // 18 等价于 times(3, 6)
	fmt.Println(timesFour(5))     // 20 等价于 times(4, 5)
	fmt.Println(timesFour(6))     // 24 等价于 times(4, 6)

	http.ListenAndServe(":8080", http.HandlerFunc(greeting))
}
